﻿using JSTT_DATA_ENTITY;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using TSComm.Utilities.Datas;

namespace JSTT_SEV_PROJECT
{
    /// <summary>
    /// 接收设备数据类
    /// </summary>
    class THRecieveDevDatas
    {
        private TcpServer tcpSev = new TcpServer();
        private int tcpSevPort = 8899;
        private DTMessageQueue dtMessageSend = new DTMessageQueue();
        private int messageCount = 1;

        private Dictionary<string, TcpServerConnection> tcpSeverConnectionList;
        private Dictionary<string, byte[]> tcpTempSendDataList;
        //private NamedPipeClient namedPipeClient = new NamedPipeClient("127.0.0.1","JSTT_PIPE");

        /// <summary>
        /// 构造函数，创建消息队列，并初始化Socket准备接收数据
        /// </summary>
        public THRecieveDevDatas()
        {
            tcpSeverConnectionList = new Dictionary<string, TcpServerConnection>();
            tcpTempSendDataList = new Dictionary<string, byte[]>();
        }

        public void ClearMessageQueue()
        {
            dtMessageSend.DeleteMessageQueue();
        }

        /// <summary>
        /// Thread , 打开端口,接收Socket数据
        /// </summary>
        public void ReceiveSocketDatas()
        {
            try
            {
                tcpSevPort = Convert.ToInt16(System.Configuration.ConfigurationManager.AppSettings["LISTENPORT"].ToString());
            }
            catch
            {
                JSTTLogger.Logger.ProcWarnLogger("tcpServerPort Get Error.");
            }
            tcpSev.OnConnect += TCPServer_OnConnect;
            tcpSev.OnDataAvailable += TCPServer_OnDataAvailable;
            tcpSev.Port = tcpSevPort;
            tcpSev.Open();

            // TODO : 在这里，程序应该判断端口是否被绑定，如果被绑定，应该需要返回异常信息等处理。
        }

        /// <summary>
        /// 当存在连接时，此函数被调用
        /// </summary>
        /// <param name="connection"></param>
        public void TCPServer_OnConnect(TcpServerConnection connection)
        {
            // Log 
        }

        /// <summary>
        /// 接收数据函数
        /// </summary>
        /// <param name="connection"></param>
        public void TCPServer_OnDataAvailable(TcpServerConnection connection)
        {
            // Log
            byte[] data = ReadStream(connection.Socket);


            string remoteIpAddress = connection.Socket.Client.RemoteEndPoint.ToString().Split(':')[0];
            string remoteIpPort = connection.Socket.Client.RemoteEndPoint.ToString().Split(':')[1];

            if (data != null)
            {
                if (data.Length > 10 && data[0] == 0x90 && data[1] == 0x91)
                {
                    // Send Data to Socket
                    ProcessClientData(data, connection);
                }
                else
                {
                    //connection.Socket.Client.AddressFamily
                    //namedPipeClient.SendMessage(data);
                    dtMessageSend.SendMessage(data);
                    JSTTLogger.Logger.RecvSocketDataLogger(data, remoteIpAddress, remoteIpPort);
                    SaveDataLog(data, remoteIpAddress, Convert.ToInt32(remoteIpPort), connection);
                    //string dataStr = Encoding.ASCII.GetString(data);
                    //Console.WriteLine((messageCount++).ToString()+". Recieve Datas:+++"+System.DateTime.Now.ToString() );
                    //connection.sendData(new byte[] { 0x68, 0x52, 0x14, 0x83, 0x35, 0x00, 0x68, 0x01, 0x00, 0x01, 0x07, 0xf7, 0x16 });

                    //DateTime dt = connection.LastVerifyTime;
                }


            }
        }

        private void ProcessClientData(byte[] data, TcpServerConnection remoteConnection)
        {
            try
            {
                byte[] dtuBytes = data.CopyBytes(2, 6);
                string dtuSim = ByteHelper.ConvertByteData(dtuBytes, "nvarchar", 6).ToString();
                if (dtuSim.Length > 11 && dtuSim[0] == '0')
                    dtuSim = dtuSim.Substring(1, 11);

                //short dtuSendTimes = Convert.ToInt16(ByteHelper.ConvertByteData(new Byte[] {data[2]}, "int", 1));

                byte[] dataLenBytes = data.CopyBytes(8, 2);
                //short dataLength = Convert.ToInt16(ByteHelper.ConvertByteData(dataLenBytes, "int", 2));
                short dataLength = System.BitConverter.ToInt16(dataLenBytes, 0);

                if (data.Length >= dataLength + 10)
                {
                    byte[] senddatas = data.CopyBytes(10, dataLength);
                    if (tcpSeverConnectionList.ContainsKey(dtuSim) == false || tcpSeverConnectionList[dtuSim] == null)
                    {
                        remoteConnection.sendData("NOSIM");
                    }
                    else if (tcpSeverConnectionList[dtuSim].verifyConnected() == false)
                    {
                        remoteConnection.sendData("WAITING");
                        tcpTempSendDataList.Add(dtuSim, senddatas);
                        tcpSeverConnectionList[dtuSim].forceDisconnect();
                    }
                    else
                    {
                        SendDataToDevice(tcpSeverConnectionList[dtuSim], dtuSim, senddatas);
                        //tcpSeverConnectionList[dtuSim].sendData(senddatas);

                        remoteConnection.sendData("SENDED");
                    }
                }
            }

            catch (Exception e)
            {
                remoteConnection.sendData("ERROR");
                return;
            }
        }

        private void SaveDataLog(byte[] data, string remoteIpAddress, int remoteIpPort, TcpServerConnection connection)
        {
            int dataLength = data.Length;
            if (dataLength > 200) // 有效范围值
            {
                int startByte = Convert.ToInt32(ByteHelper.ConvertByteData(new Byte[] { data[0] }, "int", 1));
                int endByte = Convert.ToInt32(ByteHelper.ConvertByteData(new Byte[] { data[data.Length - 1] }, "int", 1));
                string dtuSim = "";
                if (startByte == 0x68 && endByte == 0x16)
                {
                    byte[] dtuBytes = data.CopyBytes(1, 6);
                    dtuSim = ByteHelper.ConvertByteData(dtuBytes, "nvarchar", 6).ToString();
                    if (dtuSim.Length > 11 && dtuSim[0] == '0')
                        dtuSim = dtuSim.Substring(1, 11);
                    string allBytes = ByteHelper.ConvertByteData(data, "nvarchar", data.Length - 1).ToString();

                    JSTTDevDataManager.InsertReceiveLog(remoteIpAddress, remoteIpPort, allBytes, dataLength, dtuSim, "RECV");


                    //string connectionKey = remoteIpAddress + ":" + remoteIpPort.ToString();
                    if (tcpSeverConnectionList.ContainsKey(dtuSim) == false)
                    {
                        tcpSeverConnectionList.Add(dtuSim, connection);
                    }
                    else
                    {
                        tcpSeverConnectionList[dtuSim] = connection;
                    }

                    if (tcpTempSendDataList.ContainsKey(dtuSim))
                    {
                        SendDataToDevice(connection, dtuSim, tcpTempSendDataList[dtuSim]);
                        //connection.sendData(tcpTempSendDataList[dtuSim]);
                        tcpTempSendDataList.Remove(dtuSim);
                    }
                }
            }
        }

        private void SendDataToDevice(TcpServerConnection devConnection, string dtuSim, byte[] datas)
        {
            try
            {
                string devIpAddress = devConnection.Socket.Client.RemoteEndPoint.ToString().Split(':')[0];
                int devIpPort = Convert.ToInt32(devConnection.Socket.Client.RemoteEndPoint.ToString().Split(':')[1]);
                devConnection.sendData(datas);

                string sendBytes = ByteHelper.ConvertByteData(datas, "nvarchar", datas.Length - 1).ToString();
                JSTTDevDataManager.InsertReceiveLog(devIpAddress, devIpPort, sendBytes, datas.Length, dtuSim, "SEND");
            }
            catch (Exception e)
            {
                return;
            }

        }


        /// <summary>
        /// 读取Socket端发送的数据
        /// </summary>
        /// <param name="client"></param>
        /// <returns></returns>
        private byte[] ReadStream(TcpClient client)
        {
            NetworkStream stream = client.GetStream();
            if (stream.DataAvailable)
            {
                byte[] data = new byte[client.Available];

                int bytesRead = 0;
                try
                {
                    bytesRead = stream.Read(data, 0, data.Length);
                }
                catch (IOException)
                {
                }

                if (bytesRead < data.Length)
                {
                    byte[] lastData = data;
                    data = new byte[bytesRead];
                    Array.ConstrainedCopy(lastData, 0, data, 0, bytesRead);
                }
                return data;
            }
            return null;
        }
    }
}
